import { INVALID_VALUE } from './../../Core/CoreDefine';
import { ObjectWrap } from './../../Core/FrameEx/ES5Ex';
import { JXBtlMap_Spoce } from './../Views/JXBattle/JXBattleDefine';
import { BtlMapParser } from './BtlMap/BtlMapParser';
import GameMgr from './GameMgr';
import MaskUtil = require('../../Core/Manager/MaskUtil');

enum AddState {
	Add,
	Del,
	Noc
}

const DirNum = {
	top: [2, 3, 4],
	bottom: [8, 7, 6],
	left: [2, 1, 8],
	right: [4, 5, 6]
}
export default class MapMgr extends ObjectWrap {
	protected static _ins: MapMgr;
	public static get ins(): MapMgr {
		if (!this._ins) {
			this._ins = new MapMgr;
		}
		return this._ins;
	}

	constructor() {
		super();
	}

	public _fsMapPatser: BtlMapParser = null;
	private _mapId: number = INVALID_VALUE;

	public set mapId(id: number) {
		this._mapId = id;
	}

	public get mapId(): number {
		return this._mapId;
	}


	/**获取相邻地块 */
	public getAdjacent(id: number, refPos: cc.Vec2): cc.Vec2[] {
		let raw = GameMgr.scopeData.getRaw<SScopeDataRaw>(id);
		let points = [];
		switch (raw.type) {
			case JXBtlMap_Spoce.TRACK: {
				let direction = raw.scope[0];
				let num = raw.scope[1];
				direction.forEach((element, index) => {
					let dir = element;
					let isX = AddState.Noc;
					let isY = AddState.Noc;
					if (DirNum.top.indexOf(dir) != INVALID_VALUE) {
						isY = AddState.Add
					}
					if (DirNum.bottom.indexOf(dir) != INVALID_VALUE) {
						isY = AddState.Del
					}

					if (DirNum.left.indexOf(dir) != INVALID_VALUE) {
						isX = AddState.Del
					}
					if (DirNum.right.indexOf(dir) != INVALID_VALUE) {
						isX = AddState.Add
					}
					points.push(...this.getGridByDir(refPos, num[index], isX, isY))
				});
				break;
			}
			case JXBtlMap_Spoce.AROUND: {
				for (let i = refPos.x - raw.scope; i <= refPos.x + raw.scope; i++) {
					for (let j = refPos.y - raw.scope; j <= refPos.y + raw.scope; j++) {
						let grid = cc.v2(i, j);
						points.push(grid)
					}
				}
				break;
			}
			case JXBtlMap_Spoce.SECTOR: {
				let direction = raw.scope[0];
				let nums = raw.scope[1];
				direction.forEach((element, index) => {
					let dir = element;
					let num = nums[index];
					let pos = null;
					switch (dir) {
						case 1: {
							pos = this.getSectorByDir1(refPos, num, AddState.Del, AddState.Add)
							break;
						}
						case 3: {
							pos = this.getSectorByDir1(refPos, num, AddState.Add, AddState.Add)
							break;
						}
						case 5: {
							pos = this.getSectorByDir1(refPos, num, AddState.Add, AddState.Del)
							break;
						}
						case 7: {
							pos = this.getSectorByDir1(refPos, num, AddState.Del, AddState.Del)
							break;
						}
						case 8:
						case 4:
						case 6:
						case 2: {
							pos = this.getSectorByDir2(refPos, num, dir);
							break;
						}
					}
					points.push(...pos)
				})
				break;
			}
			case JXBtlMap_Spoce.MAP: {
				let arr = raw.scope as number[];
				arr.forEach(id => {
					points.push(this.decodeXxyy(id))
				})
				break;
			}
		}
		return points;
	}

	protected getGridByDir(pos: cc.Vec2, num: number, isX: AddState, isY: AddState) {
		let posArr = []
		let offset = 1;
		for (let i = 0; i < num; i++) {
			let ele = cc.v2();
			ele.x = pos.x;
			ele.y = pos.y;
			if (isX === AddState.Add) {
				ele.x += offset;
			} else if (isX === AddState.Del) {
				ele.x -= offset;
			}

			if (isY === AddState.Add) {
				ele.y += offset;
			} else if (isY === AddState.Del) {
				ele.y -= offset;
			}
			offset++;
			posArr.push(ele)
		}
		return posArr;
	}

	/**扇形1 */
	protected getSectorByDir1(pos: cc.Vec2, num: number, isX: AddState, isY: AddState) {
		let arr = [];
		if (isX === AddState.Add) {
			for (let i = 1; i <= num + 1; i++) {
				if (isY === AddState.Add) {
					for (let j = 1; j <= num + 1 - i; j++) {
						let point = cc.v2();
						point.x = pos.x + i;
						point.y = pos.y + j;
						arr.push(point)
					}
				} else {
					for (let j = -1; j >= -num - 1 + i; j--) {
						let point = cc.v2();
						point.x = pos.x + i;
						point.y = pos.y + j;
						arr.push(point)
					}
				}
			}
		} else {
			for (let i = -1; i >= -num - 1; i--) {
				if (isY === AddState.Add) {
					for (let j = 1; j <= num + 1 - Math.abs(i); j++) {
						let point = cc.v2();
						point.x = pos.x + i;
						point.y = pos.y + j;
						arr.push(point)
					}
				} else {
					for (let j = -1; j >= -num - 1 + Math.abs(i); j--) {
						let point = cc.v2();
						point.x = pos.x + i;
						point.y = pos.y + j;
						arr.push(point)
					}
				}
			}
		}
		return arr;
	}

	protected getSectorByDir2(pos: cc.Vec2, num: number, dir: number) {
		let arr = [];
		for (let i = 1; i <= num; i++) {
			for (let j = 0; j <= i - 1; j++) {
				let point = cc.v2();
				let point2 = cc.v2();
				if (dir === 2) {
					point.x = pos.x + j;
					point.y = pos.y + i;
					point2.x = pos.x - j;
					point2.y = pos.y + i;
					arr.push(point);
					arr.push(point2);
				} else if (dir === 4) {
					point.y = pos.y + j;
					point.x = pos.x + i;
					point2.y = pos.y - j;
					point2.x = pos.x + i;
					arr.push(point);
					arr.push(point2);
				} else if (dir === 6) {
					point.y = pos.y - i;
					point.x = pos.x - j;
					point2.y = pos.y - i;
					point2.x = pos.x + j;
					arr.push(point);
					arr.push(point2);
				} else if (dir === 8) {
					point.y = pos.y - j;
					point.x = pos.x - i;
					point2.y = pos.y + j;
					point2.x = pos.x - i;
					arr.push(point);
					arr.push(point2);
				}

			}
		}
		return arr;
	}


	public encodeXxyy(pos: cc.Vec2) {
		return pos.x * 100 + pos.y;
	}

	public decodeXxyy(xxyy: number): cc.Vec2 {
		let x = xxyy / 100 | 0;
		let y = xxyy % 100;
		return cc.v2(x, y);
	}

}